package com.example.shutdown_v1.schedule;

import com.example.shutdown_v1.dto.SensorDataPacket;
import com.example.shutdown_v1.entity.Sensor;
import com.example.shutdown_v1.repository.SensorRepository;
import com.example.shutdown_v1.service.RedisSensorDataService;
import com.example.shutdown_v1.service.ValveStateRecognitionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 每日自动校准定时任务（仅针对IM600传感器）
 * 
 * 功能: 每天早上8点对所有处于"关闭"状态的IM600传感器进行自动校准
 * 原理: 
 *   1. 获取所有IM600传感器
 *   2. 从Redis获取最新状态
 *   3. 如果状态为"closed"且在线，执行校准
 * 
 * 执行时间: 每天早上08:00:00
 */
@Slf4j
@Component
@RequiredArgsConstructor
@ConditionalOnProperty(
    prefix = "schedule.auto-calibration",
    name = "enabled",
    havingValue = "true",
    matchIfMissing = true
)
public class DailyAutoCalibrationScheduler {
    
    private final SensorRepository sensorRepository;
    private final ValveStateRecognitionService recognitionService;
    
    @Autowired(required = false)
    private RedisSensorDataService redisSensorDataService;
    
    /**
     * 每天早上8点执行自动校准
     */
    @Scheduled(cron = "${schedule.auto-calibration.cron:0 0 8 * * ?}")
    public void performDailyAutoCalibration() {
        log.info("========================================");
        log.info("[定时任务] 开始每日自动校准... 时间: {}", LocalDateTime.now());
        
        try {
            // 查询所有传感器
            List<Sensor> allSensors = sensorRepository.findAll();
            
            if (allSensors.isEmpty()) {
                log.info("[定时任务] 没有传感器需要校准");
                return;
            }
            
            log.info("[定时任务] 找到 {} 个传感器，开始检查状态...", allSensors.size());
            
            int totalCount = 0;
            int skippedCount = 0;
            int failedCount = 0;
            
            for (Sensor sensor : allSensors) {
                try {
                    // 所有传感器统一进行自动校准（都是IM600）
                    
                    // 从Redis获取最新状态和数据
                    if (redisSensorDataService == null) {
                        log.warn("[{}] Redis服务未启用，跳过校准", sensor.getSensorId());
                        skippedCount++;
                        continue;
                    }
                    
                    // 使用小写传感器ID查询Redis（修复大小写不匹配问题）
                    String sensorIdLowerCase = sensor.getSensorId().toLowerCase();
                    Map<String, Object> statusMap = redisSensorDataService.getSensorStatus(sensorIdLowerCase);
                    String state = (String) statusMap.getOrDefault("state", "unknown");
                    Boolean isOnline = (Boolean) statusMap.getOrDefault("isOnline", false);
                    
                    // 只有在线且处于"关闭"状态的传感器才进行校准
                    if (!isOnline) {
                        log.debug("[{}] 传感器离线，跳过校准", sensor.getSensorId());
                        skippedCount++;
                        continue;
                    }
                    
                    if (!"closed".equals(state)) {
                        log.debug("[{}] 传感器状态为 {}，不是关闭状态，跳过校准", sensor.getSensorId(), state);
                        skippedCount++;
                        continue;
                    }
                    
                    // 从Redis状态中构建传感器数据包
                    SensorDataPacket packet = buildSensorDataPacketFromStatus(sensor.getSensorId(), statusMap);
                    
                    if (packet == null) {
                        log.warn("[{}] 数据包构建失败，跳过校准", sensor.getSensorId());
                        skippedCount++;
                        continue;
                    }
                    
                    // 执行IM600自动校准
                    recognitionService.triggerIM600AutoCalibration(sensor, packet);
                    totalCount++;
                    
                } catch (Exception e) {
                    log.error("[传感器:{}] 自动校准失败: {}", sensor.getSensorId(), e.getMessage(), e);
                    failedCount++;
                }
            }
            
            log.info("========================================");
            log.info("[定时任务] IM600每日自动校准完成");
            log.info("   总传感器数: {}", allSensors.size());
            log.info("   成功校准(IM600): {}", totalCount);
            log.info("   跳过: {}", skippedCount);
            log.info("   失败: {}", failedCount);
            log.info("========================================");
            
        } catch (Exception e) {
            log.error("[定时任务] 每日自动校准任务执行失败", e);
        }
    }
    
    /**
     * 从Redis状态Map构建传感器数据包
     * 注意：Redis状态中包含了最新的传感器数据
     */
    private SensorDataPacket buildSensorDataPacketFromStatus(String sensorId, Map<String, Object> statusMap) {
        try {
            return SensorDataPacket.builder()
                    .mac(sensorId)
                    .roll(getDoubleValue(statusMap, "roll"))
                    .pitch(getDoubleValue(statusMap, "pitch"))
                    .yaw(getDoubleValue(statusMap, "yaw"))
                    .accelX(getDoubleValue(statusMap, "accelX"))
                    .accelY(getDoubleValue(statusMap, "accelY"))
                    .accelZ(getDoubleValue(statusMap, "accelZ"))
                    .build();
        } catch (Exception e) {
            log.error("[{}] 构建数据包失败: {}", sensorId, e.getMessage());
            return null;
        }
    }
    
    /**
     * 从Map中安全获取Double值
     */
    private Double getDoubleValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        }
        if (value instanceof String) {
            try {
                return Double.parseDouble((String) value);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }
    
    /**
     * 手动触发自动校准（用于测试）
     */
    public void manualTrigger() {
        log.info("[手动触发] 开始执行自动校准...");
        performDailyAutoCalibration();
    }
}

